Skip to content

Refactor Channel creation #377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Jun 28, 2021
Merged

Conversation

fabianfett
Copy link
Member

This is the first cherry pick from #376.

  • The connection creation logic has been refactored into a number of smaller methods that can be combined for the configuration.
  • Connection creation now has a logical home. We move it from Utils.swift into a ConnectionFactory
  • We have explicit ChannelHandlers that we use for connection creation:
    • TLSEventsHandler got its own file and unit tests
    • HTTP1ProxyConnectHandler got its own file and unit tests
  • Some small things are already part of this pr that will get their context later. For example:
    • HTTPConnectionPool is added as a namespace to not cause major renames in follow up PRs
    • HTTPConnectionPool.Connection.ID and its generator were added now. (This will be used later to identify a connection during its lifetime)
    • the file HTTPConnectionPool+Manager was added to give HTTPConnectionPool.Connection.ID.Generator already its final destination.

Looking forward to your feedback.
I'm well aware that this PR is in a race with #375. I'm happy to update it once #375 has landed.

@fabianfett fabianfett force-pushed the ff-channel-creation branch 5 times, most recently from b97d82c to 0a6bef5 Compare June 16, 2021 21:46
@fabianfett
Copy link
Member Author

Ran into a test failure in Swift 5.1: testSSLHandshakeErrorPropagation failed.

Looks like this one used to be flaky. But I assume @Lukasa fixed it with #335. Investigated the test's flakyness with 100 iterations in Xcode (all passed). Will need further investigation on Linux.

@fabianfett fabianfett requested a review from artemredkin June 16, 2021 22:02
@Lukasa Lukasa added the 🔨 semver/patch No public API change. label Jun 17, 2021
static var globalGenerator = Generator()

struct Generator {
private let atomic: NIOAtomic<Int>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can make it UInt64, just in case someone will be running it until our sun dies 😆

Copy link
Collaborator

@artemredkin artemredkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor suggestions, but otherwise looks good 👍

var isIPAddress: Bool {
var ipv4Addr = in_addr()
var ipv6Addr = in6_addr()

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

@fabianfett fabianfett force-pushed the ff-channel-creation branch 5 times, most recently from 1b08850 to ed91313 Compare June 21, 2021 14:42
Comment on lines 265 to 336
#if canImport(Network)
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *), let tsBootstrap = NIOTSConnectionBootstrap(validatingGroup: eventLoop) {
// create NIOClientTCPBootstrap with NIOTS TLS provider
let bootstrapFuture = tlsConfig.getNWProtocolTLSOptions(on: eventLoop).map {
options -> NIOClientTCPBootstrapProtocol in

tsBootstrap
.addTimeoutIfNeeded(self.clientConfiguration.timeout)
.tlsOptions(options)
.channelInitializer { channel in
do {
try channel.pipeline.syncOperations.addHandler(HTTPClient.NWErrorHandler())
// we don't need to set a TLS deadline for NIOTS connections, since the
// TLS handshake is part of the TS connection bootstrap. If the TLS
// handshake times out the complete connection creation will be failed.
try channel.pipeline.syncOperations.addHandler(TLSEventsHandler(deadline: nil))
return channel.eventLoop.makeSucceededFuture(())
} catch {
return channel.eventLoop.makeFailedFuture(error)
}
} as NIOClientTCPBootstrapProtocol
}
return bootstrapFuture
}
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section is kind of rough to read, could it be refactored a little to have less indentation?

guard let connectTimeamount = config?.connect else {
return self
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

@fabianfett fabianfett force-pushed the ff-channel-creation branch 3 times, most recently from f4ce479 to 638bce9 Compare June 23, 2021 08:14
@fabianfett fabianfett force-pushed the ff-channel-creation branch from 10f24b9 to 1353129 Compare June 23, 2021 14:54
@fabianfett fabianfett requested review from Davidde94 and Lukasa June 23, 2021 14:55
@fabianfett fabianfett force-pushed the ff-channel-creation branch from 1353129 to f92293f Compare June 23, 2021 14:59
@fabianfett fabianfett added this to the 1.5.0 milestone Jun 23, 2021
@fabianfett fabianfett force-pushed the ff-channel-creation branch from b489196 to 7aec48b Compare June 25, 2021 10:16

func handlerAdded(context: ChannelHandlerContext) {
self.proxyEstablishedPromise = context.eventLoop.makePromise(of: Void.self)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!

case .connectSent(let timeout), .headReceived(let timeout):
timeout.cancel()
self.failWithError(HTTPClientError.remoteConnectionClosed, context: context, closeConnection: false)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change


case .connectSent, .headReceived:
self.failWithError(HTTPClientError.httpProxyHandshakeTimeout, context: context)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

switch self.state {
case .initialized:
preconditionFailure("How can we have a scheduled timeout, if the connection is not even up?")

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

self.state = .headReceived(scheduled)
case 407:
self.failWithError(HTTPClientError.proxyAuthenticationRequired, context: context)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

timeout.cancel()
self.state = .completed
self.proxyEstablishedPromise?.succeed(())

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change


func handlerAdded(context: ChannelHandlerContext) {
self.socksEstablishedPromise = context.eventLoop.makePromise(of: Void.self)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

case .https, .https_unix:
return self.makeTLSChannel(deadline: deadline, eventLoop: eventLoop, logger: logger).flatMapThrowing {
channel, negotiated in

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

@fabianfett fabianfett force-pushed the ff-channel-creation branch from 40d73e2 to 761b699 Compare June 28, 2021 10:22
Copy link
Collaborator

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@fabianfett fabianfett merged commit 8e4d519 into swift-server:main Jun 28, 2021
@fabianfett fabianfett deleted the ff-channel-creation branch June 28, 2021 11:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🆕 semver/minor Adds new public API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants